//
//  UIView+EXtension.m
//  ZPIOSEducation
//
//  Created by 李伟 on 2016/11/23.
//  Copyright © 2016年 liwei. All rights reserved.
//

#import "UIView+EXtension.h"
#import "objc/runtime.h"

UIInterfaceOrientation ITTInterfaceOrientation() {
    UIInterfaceOrientation orient = [UIApplication sharedApplication].statusBarOrientation;
    return orient;
}

CGRect ITTScreenBounds() {
    CGRect bounds = [UIScreen mainScreen].bounds;
    if (UIInterfaceOrientationIsLandscape(ITTInterfaceOrientation())) {
        CGFloat width = bounds.size.width;
        bounds.size.width = bounds.size.height;
        bounds.size.height = width;
    }
    return bounds;
}

@implementation UIView (EXtension)
// width //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_width
{
    return self.frame.size.width;
}
- (void)setXj_width:(CGFloat)xj_width
{
    CGRect frame = self.frame;
    frame.size.width = xj_width;
    self.frame = frame;
}

// height //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_height
{
    return self.frame.size.height;
}
- (void)setXj_height:(CGFloat)xj_height
{
    CGRect frame = self.frame;
    frame.size.height = xj_height;
    self.frame = frame;
}

// x //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_x
{
    return self.frame.origin.x;
}
- (void)setXj_x:(CGFloat)xj_x
{
    CGRect frame = self.frame;
    frame.origin.x = xj_x;
    self.frame = frame;
}

// y //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_y
{
    return self.frame.origin.y;
}
- (void)setXj_y:(CGFloat)xj_y
{
    CGRect frame = self.frame;
    frame.origin.y = xj_y;
    self.frame = frame;
}

// center-X //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_centerX
{
    return self.center.x;
}
- (void)setXj_centerX:(CGFloat)xj_centerX
{
    CGPoint center = self.center;
    center.x = xj_centerX;
    self.center = center;
}

// center-Y //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_centerY
{
    return self.center.y;
}
- (void)setXj_centerY:(CGFloat)xj_centerY
{
    CGPoint center = self.center;
    center.y = xj_centerY;
    self.center = center;
}

// top //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_top
{
    return self.frame.origin.y;
}
- (void)setXj_top:(CGFloat)xj_top
{
    CGRect frame = self.frame;
    frame.origin.y = xj_top;
    self.frame = frame;
}

// bottom //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_bottom
{
    return CGRectGetMaxY(self.frame);
}
- (void)setXj_bottom:(CGFloat)xj_bottom
{
    self.xj_y = xj_bottom - self.xj_height;
}

// left //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_left
{
    return self.frame.origin.x;
}
- (void)setXj_left:(CGFloat)xj_left
{
    CGRect frame = self.frame;
    frame.origin.x = xj_left;
    self.frame = frame;
}

// right //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_right
{
    return CGRectGetMaxX(self.frame);
}
- (void)setXj_right:(CGFloat)xj_right
{
    self.xj_x = xj_right - self.xj_width;
}

// screenX //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_screenX
{
    CGFloat x = 0;
    for (UIView* view = self; view; view = view.superview) {
        x += view.xj_left;
    }
    return x;
}

// screenY //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_screenY
{
    CGFloat y = 0;
    for (UIView* view = self; view; view = view.superview) {
        y += view.xj_top;
    }
    return y;
}

// size //////////////////////////////////////////////////////////////////////////////////
- (CGSize)xj_framesize
{
    return self.frame.size;
}
- (void)setXj_framesize:(CGSize)xj_framesize
{
    CGRect frame = self.frame;
    frame.size = xj_framesize;
    self.frame = frame;
}

// scerrnViewX //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_screenViewX
{
    CGFloat x = 0;
    for (UIView* view = self; view; view = view.superview) {
        x += view.xj_left;
        
        if ([view isKindOfClass:[UIScrollView class]]) {
            UIScrollView* scrollView = (UIScrollView*)view;
            x -= scrollView.contentOffset.x;
        }
    }
    return x;
}

// scerrnViewY //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_screenViewY
{
    CGFloat y = 0;
    for (UIView* view = self; view; view = view.superview) {
        y += view.xj_top;
        
        if ([view isKindOfClass:[UIScrollView class]]) {
            UIScrollView* scrollView = (UIScrollView*)view;
            y -= scrollView.contentOffset.y;
        }
    }
    return y;
}

// screenFrame //////////////////////////////////////////////////////////////////////////////////
- (CGRect)xj_screenFrame
{
    return CGRectMake(self.xj_screenViewX, self.xj_screenViewY, self.xj_width, self.xj_height);
}

// frameorigin //////////////////////////////////////////////////////////////////////////////////
- (CGPoint)xj_frameorigin
{
    return self.frame.origin;
}
- (void)setXj_frameorigin:(CGPoint)xj_frameorigin
{
    CGRect frame = self.frame;
    frame.origin = xj_frameorigin;
    self.frame = frame;
}

// orientationWidth //////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_orientationWidth
{
    return UIInterfaceOrientationIsLandscape(ITTInterfaceOrientation())
    ? self.xj_height : self.xj_width;
}

// orientationHeight /////////////////////////////////////////////////////////////////////////////////
- (CGFloat)xj_orientationHeight
{
    return UIInterfaceOrientationIsLandscape(ITTInterfaceOrientation())
    ? self.xj_width : self.xj_height;
}

/////////////////////////////////////////////////////////////////////////////////////////
- (UIView *)descendantOrSelfWithClass:(Class)cls
{
    if ([self isKindOfClass:cls])
        return self;
    for (UIView* child in self.subviews) {
        UIView* it = [child descendantOrSelfWithClass:cls];
        if (it)
            return it;
    }
    return nil;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
- (UIView *)ancestorOrSelfWithClass:(Class)cls
{
    if ([self isKindOfClass:cls]) {
        return self;
        
    } else if (self.superview) {
        return [self.superview ancestorOrSelfWithClass:cls];
        
    } else {
        return nil;
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)removeAllSubviews {
    while (self.subviews.count) {
        UIView* child = self.subviews.lastObject;
        [child removeFromSuperview];
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
- (CGPoint)offsetFromView:(UIView*)otherView
{
    CGFloat x = 0, y = 0;
    for (UIView* view = self; view && view != otherView; view = view.superview) {
        x += view.xj_left;
        y += view.xj_right;
    }
    return CGPointMake(x, y);
}

///////////////////////////////////////////////////////////////////////////////////////////////////
- (BOOL)isShowingOnKeyWindow
{
    // 主窗口
    UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
    
    // 以主窗口左上角为坐标原点, 计算self的矩形框
    CGRect newFrame = [keyWindow convertRect:self.frame fromView:self.superview];
    CGRect winBounds = keyWindow.bounds;
    
    // 主窗口的bounds 和 self的矩形框 是否有重叠
    BOOL intersects = CGRectIntersectsRect(newFrame, winBounds);
    
    return !self.isHidden && self.alpha > 0.01 && self.window == keyWindow && intersects;
}


#pragma mark - <添加一个string的tag属性>
static void *TagStrKey = &TagStrKey;
- (NSString *)tagStr
{
    return objc_getAssociatedObject(self, TagStrKey);
}

- (void)setTagStr:(NSString *)tagStr
{
    objc_setAssociatedObject(self, TagStrKey, tagStr, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

///////////////////////////////////////////////////////////////////////////////////////////////////
-(void)clipRectCornerWithDirection:(UIRectCorner)rectCorner cornerRadius:(CGFloat)cornerRadius {
    CGRect bounds = self.bounds;
    CGSize cornerSize = CGSizeMake(cornerRadius, cornerRadius);
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:rectCorner cornerRadii:cornerSize];
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = bounds;
    maskLayer.path = maskPath.CGPath;
    [self.layer addSublayer:maskLayer];
    self.layer.mask = maskLayer;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - <动画相关>
- (void)zp_addAnimationAtPoint:(CGPoint)point;
{
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    CGFloat diameter = [self zp_mdShapeDiameterForPoint:point];
    shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter);
    shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath;
    [self.layer addSublayer:shapeLayer];
    shapeLayer.fillColor = [UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1.0].CGColor;
    // animate
    CGFloat scale = 100.0 / shapeLayer.frame.size.width;
    NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault;
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
    animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
    animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName];
    animation.removedOnCompletion = YES;
    animation.duration = 3.0;
    shapeLayer.transform = [animation.toValue CATransform3DValue];
    
    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        [shapeLayer removeFromSuperlayer];
    }];
    [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"];
    [CATransaction commit];
}

///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)zp_addAnimationAtPoint:(CGPoint)point WithType:(ZPAnimationType) type withColor:(UIColor *)animationColor completion:(void (^)(BOOL))completion
{
    [self zp_addAnimationAtPoint:point WithDuration:1.0 WithType:type withColor:animationColor  completion:completion];
}

///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)zp_addAnimationAtPoint:(CGPoint)point WithDuration:(NSTimeInterval)duration WithType:(ZPAnimationType) type withColor:(UIColor *)animationColor completion:(void (^)(BOOL finished))completion
{
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    CGFloat diameter = [self zp_mdShapeDiameterForPoint:point];
    shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter);
    shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath;
    
    shapeLayer.fillColor = animationColor.CGColor;
    // animate
    CGFloat scale = 1.0 / shapeLayer.frame.size.width;
    NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault;
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
    switch (type) {
        case ZPAnimationOpen:
        {
            [self.layer addSublayer:shapeLayer];
            animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
            animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)];
            break;
        }
        case ZPAnimationClose:
        {
            [self.layer insertSublayer:shapeLayer atIndex:0];
            animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)];
            animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
            break;
        }
        default:
            break;
    }
    animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName];
    animation.removedOnCompletion = YES;
    animation.duration = duration;
    shapeLayer.transform = [animation.toValue CATransform3DValue];
    
    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        [shapeLayer removeFromSuperlayer];
        completion(true);
    }];
    [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"];
    [CATransaction commit];
    
}

///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)zp_addAnimationAtPoint:(CGPoint)point WithType:(ZPAnimationType) type withColor:(UIColor *)animationColor;
{
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    CGFloat diameter = [self zp_mdShapeDiameterForPoint:point];
    shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter);
    shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath;
    
    shapeLayer.fillColor = animationColor.CGColor;
    // animate
    CGFloat scale = 100.0 / shapeLayer.frame.size.width;
    NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault;
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
    switch (type) {
        case ZPAnimationOpen:
        {
            [self.layer addSublayer:shapeLayer];
            animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
            animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)];
            break;
        }
        case ZPAnimationClose:
        {
            [self.layer insertSublayer:shapeLayer atIndex:0];
            animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)];
            animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
            break;
        }
        default:
            break;
    }
    animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName];
    animation.removedOnCompletion = YES;
    animation.duration = 3.0;
    shapeLayer.transform = [animation.toValue CATransform3DValue];
    
    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        [shapeLayer removeFromSuperlayer];
    }];
    [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"];
    [CATransaction commit];
}


///////////////////////////////////////////////////////////////////////////////////////////////////
// 计算离屏幕的边框最大的距离
- (CGFloat)zp_mdShapeDiameterForPoint:(CGPoint)point
{
    CGPoint cornerPoints[] = {
        {0.0, 0.0},
        {0.0, self.bounds.size.height},
        {self.bounds.size.width, self.bounds.size.height},
        {self.bounds.size.width, 0.0}
    };
    
    CGFloat radius = 0.0;
    for (int i = 0; i < 4; i++)
    {
        CGPoint p = cornerPoints[i];
        CGFloat d = sqrt( pow(p.x - point.x, 2.0) + pow(p.y - point.y, 2.0));
        if (d > radius)
        {
            radius = d;
        }
    }
    return radius * 2.0;
}
@end
